﻿#include "FITKAcousticsVTKGraphObjectSEAFreeEdges.h"
#include "FITKAcousticsVTKGraphActor.h"

// VTK
#include <vtkProperty.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPoints.h>

// Data
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"

// Graph and filter
#include "FITKAcousticsVTKCommons.h"
#include "FITKAcousticsVTKSharedDataManager.h"
#include "FITK_Interface/FITKVTKAlgorithm/FITKGraphActor.h"

namespace Exchange
{
    FITKAcousticsVTKGraphObjectSEAFreeEdges::FITKAcousticsVTKGraphObjectSEAFreeEdges(Acoustics::FITKAcousticsSEAModel* model)
        : FITKAcousticsVTKGraphObject3D(model)
    {
        // Return if the input is nullptr.
        if (!model)
        {
            return;
        }

        // Intiailize the polygon offset.
        m_polygonOffset = FITKAcousticsVTKCommons::s_polygonOffsetTopMarks;

        // Initialize vtk objects.
        init();

        // Generate the nodes actor.
        generateGraph();

        // Update the visibility.
        updateVisibility();

        // Save the data type.
        m_graphInfo.Type = FITKAcousticsVTKCommons::FreeEdgesGraph;
    }

    FITKAcousticsVTKGraphObjectSEAFreeEdges::~FITKAcousticsVTKGraphObjectSEAFreeEdges()
    {
        // Delete vtk objects.
        deleteVtkObj(m_ugrid);
    }

    void FITKAcousticsVTKGraphObjectSEAFreeEdges::init()
    {
        // Create the grid.
        m_ugrid = vtkUnstructuredGrid::New();        

        // Get the points in shared data.
        vtkPoints* points = FITKAcousticsVTKSharedDataManager::GetInstance()->getSEANodesPoints();
        m_ugrid->SetPoints(points);
    }

    void FITKAcousticsVTKGraphObjectSEAFreeEdges::update(bool forceUpdate)
    {
        Acoustics::FITKAcousticsSEAModel* model = dynamic_cast<Acoustics::FITKAcousticsSEAModel*>(_dataObj);
        if (!model || !m_ugrid)
        {
            return;
        }

        // This graph object must re-generate the data set.
        Q_UNUSED(forceUpdate);

        // Reset vtk data.
        resetVtkObj(m_ugrid);

        // Re-generate the data set.
        generateDataSet(model);

        // Update the pipeline.
        m_ugrid->Modified();

        // Update the visibility.
        updateVisibility();
    }

    void FITKAcousticsVTKGraphObjectSEAFreeEdges::updateVisibility()
    {
        // Get the runtime settings for visibility.
        bool showFreeEdges = getRuntimeSettingAs<bool>(RTS_KEY_VISIBLE_SEA_FREE_EDGES, false);

        // Update the visibility with the flags.
        //@{
        // Show or hide actors.
        setVisible(showFreeEdges);
        //@}
    }

    bool FITKAcousticsVTKGraphObjectSEAFreeEdges::generateDataSet(Acoustics::FITKAcousticsSEAModel* model)
    {
        // Get the SEA nodes.
        Acoustics::FITKAcousticsDiscModel* discModel = FITKGLODATA->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)return false;
        Acoustics::FITKAcousticsDiscNodeList* seaNodes = discModel->getNodes();
        if (!seaNodes)
        {
            return false;
        }

        // Get the free edges of the SEA model.
        QList<QPair<int, int>> edges = discModel->getFreeEdge();

        for (const QPair<int, int> & edge : edges)
        {
            int ptIndex_1 = seaNodes->getNodeIndexByID(edge.first);
            int ptIndex_2 = seaNodes->getNodeIndexByID(edge.second);

            // Create the line cell.
            vtkSmartPointer<vtkIdList> cell = vtkSmartPointer<vtkIdList>::New();
            cell->InsertNextId(ptIndex_1);
            cell->InsertNextId(ptIndex_2);
            m_ugrid->InsertNextCell(VTKCellType::VTK_LINE, cell);
        }

        return true;
    }

    void FITKAcousticsVTKGraphObjectSEAFreeEdges::generateGraph()
    {
        // Create grid actor.
        m_fActor = FITKAcousticsVTKGraphActor::New();
        m_fActor->setGraphObject(this);
        m_fActor->setActorType(ActorType::EdgeActor);
        m_fActor->SetPickable(false);
        m_fActor->SetVisibility(true);
        m_fActor->GetProperty()->SetRepresentation(1);
        m_fActor->GetProperty()->SetPointSize(0.);
        m_fActor->GetProperty()->SetLineWidth(3.);
        m_fActor->setRelativeCoincidentTopologyPolygonOffsetParameters(m_polygonOffset);
        addActor(m_fActor);

        // Initialize the color.
        double color3[3]{ 0., 0., 0. };
        FITKAcousticsVTKCommons::QColorToDouble3(FITKAcousticsVTKCommons::s_SEAFreeEdgesColor, color3);
        m_fActor->GetProperty()->SetColor(color3);

        // Set the input data.
        m_fActor->setInputDataObject(m_ugrid);    
    }
}   // namespace Exchange